From 1ac4cf5651e58f177621450342a943ee5457cf0a Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 21 Jan 2010 09:11:06 +0000 Subject: [PATCH] VT-d: handle return value of deassign_device deassign_device may fail, so need to capture its failure for appropriate handling. This patch captures return values of deassign_device, and prints error messages if it fails. In addition, this patch also fixes some code style issues. Signed-off-by: Weidong Han --- xen/arch/ia64/xen/dom0_ops.c | 18 ++++++++++++------ xen/arch/x86/domctl.c | 21 ++++++++++----------- xen/drivers/passthrough/iommu.c | 16 ++++++++++++---- xen/drivers/passthrough/pci.c | 5 ++++- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/xen/arch/ia64/xen/dom0_ops.c b/xen/arch/ia64/xen/dom0_ops.c index 7a5e4ef20d..a8f3024727 100644 --- a/xen/arch/ia64/xen/dom0_ops.c +++ b/xen/arch/ia64/xen/dom0_ops.c @@ -354,8 +354,10 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) } ret = assign_device(d, bus, devfn); - gdprintk(XENLOG_INFO, "XEN_DOMCTL_assign_device: bdf = %x:%x.%x\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + if ( ret ) + gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: " + "assign device (%x:%x.%x) failed\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); put_domain(d); } break; @@ -388,10 +390,14 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) if ( !device_assigned(bus, devfn) ) break; - ret = 0; - deassign_device(d, bus, devfn); - gdprintk(XENLOG_INFO, "XEN_DOMCTL_deassign_device: bdf = %x:%x.%x\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + spin_lock(&pcidevs_lock); + ret = deassign_device(d, bus, devfn); + spin_unlock(&pcidevs_lock); + if ( ret ) + gdprintk(XENLOG_ERR, "XEN_DOMCTL_deassign_device: " + "deassign device (%x:%x.%x) failed\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + put_domain(d); } break; diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index b59bc9b6c6..e74e9786f7 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -842,12 +842,9 @@ long arch_do_domctl( if ( !iommu_pv_enabled && !is_hvm_domain(d) ) { ret = -ENOSYS; - put_domain(d); - break; + goto assign_device_out; } - ret = -EINVAL; - ret = assign_device(d, bus, devfn); if ( ret ) gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: " @@ -872,7 +869,7 @@ long arch_do_domctl( if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) ) { gdprintk(XENLOG_ERR, - "XEN_DOMCTL_deassign_device: get_domain_by_id() failed\n"); + "XEN_DOMCTL_deassign_device: get_domain_by_id() failed\n"); break; } @@ -886,15 +883,15 @@ long arch_do_domctl( if ( !iommu_pv_enabled && !is_hvm_domain(d) ) { ret = -ENOSYS; - put_domain(d); - break; + goto deassign_device_out; } - ret = 0; spin_lock(&pcidevs_lock); ret = deassign_device(d, bus, devfn); spin_unlock(&pcidevs_lock); - gdprintk(XENLOG_INFO, "XEN_DOMCTL_deassign_device: bdf = %x:%x.%x\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + if ( ret ) + gdprintk(XENLOG_ERR, "XEN_DOMCTL_deassign_device: " + "deassign device (%x:%x.%x) failed\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); deassign_device_out: put_domain(d); @@ -948,7 +945,7 @@ long arch_do_domctl( ret = -EPERM; if ( !IS_PRIV(current->domain) && !irq_access_permitted(current->domain, bind->machine_irq) ) - goto bind_out; + goto unbind_out; if ( iommu_enabled ) { @@ -958,6 +955,8 @@ long arch_do_domctl( } if ( ret < 0 ) gdprintk(XENLOG_ERR, "pt_irq_destroy_bind failed!\n"); + + unbind_out: rcu_unlock_domain(d); } break; diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index e4bd3cbbdf..5c4a3d5e86 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -234,23 +234,31 @@ int deassign_device(struct domain *d, u8 bus, u8 devfn) { struct hvm_iommu *hd = domain_hvm_iommu(d); struct pci_dev *pdev = NULL; + int ret = 0; if ( !iommu_enabled || !hd->platform_ops ) return -EINVAL; ASSERT(spin_is_locked(&pcidevs_lock)); pdev = pci_get_pdev(bus, devfn); - if (!pdev) + if ( !pdev ) return -ENODEV; - if (pdev->domain != d) + if ( pdev->domain != d ) { gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: deassign a device not owned\n"); return -EINVAL; } - hd->platform_ops->reassign_device(d, dom0, bus, devfn); + ret = hd->platform_ops->reassign_device(d, dom0, bus, devfn); + if ( ret ) + { + gdprintk(XENLOG_ERR VTDPREFIX, + "Deassign device (%x:%x.%x) failed!\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + return ret; + } if ( !has_arch_pdevs(d) && need_iommu(d) ) { @@ -258,7 +266,7 @@ int deassign_device(struct domain *d, u8 bus, u8 devfn) hd->platform_ops->teardown(d); } - return 0; + return ret; } int iommu_setup(void) diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index 31a969f5c2..75de82a90d 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -286,7 +286,10 @@ void pci_release_devices(struct domain *d) { pci_cleanup_msi(pdev); bus = pdev->bus; devfn = pdev->devfn; - deassign_device(d, bus, devfn); + if ( deassign_device(d, bus, devfn) ) + printk("domain %d: deassign device (%02x:%02x.%x) failed!\n", + d->domain_id, pdev->bus, PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn)); } spin_unlock(&pcidevs_lock); } -- 2.30.2